<?php
class UserController extends Controller
{
	protected $_navId = 'users';
	
	public function actionList()
	{
		$userAddForm = new UserAddForm();
		$user = new User();
		
		$postData = app()->request->getPost('UserAddForm', null);
		if($postData){
			$userAddForm->attributes = $postData;
			$ret = false;
			$detail = $errors = null;
			if($userAddForm->validate()){
				$user->attributes = $postData;
				if(!($ret = $user->save(true))){
					$errors = $user->getErrors();
				}else{
					app()->__Whatever__Log->recordUserAction(SystemLog::USER_ADD, $user->username, $user->id_user);
					$user->initIndividualConfig();
					
					$detail = $postData;
					$detail['id_user'] = $user->getPrimaryKey();
				}
			}else{
				$errors = $userAddForm->getErrors();
			}
			$this->_returnAjax(
				array(
					'result' => $ret,
					'detail' => $detail,
					'errors' => $errors
				)
			);
		}
		
		$this->render('list', array(
			'userAddForm' => $userAddForm,
			'userEditForm' => new UserEditForm(),
			'user' => $user
		));
	}
	
	public function actionEdit()
    {
		if(app()->request->isAjaxRequest){
	        $postData = app()->request->getParam('UserEditForm', null);
	    	if($postData){
	    		$userEditForm = new UserEditForm();
	    		$userEditForm->attributes = $postData;
				$ret = false;
				$detail = $errors = null;
				if($userEditForm->validate()){
					unset($postData['password_confirm']);
					$user = $this->loadModelByPk($postData['id_user'], 'User');
	            	if(empty($postData['password'])){
	            		unset($postData['password']);
	            		$user->EnP = false;
					}
					$user->attributes = $postData;
					$ret = $user->save();
					if($ret){
						if(app()->user->getData('id_user') == $user->id_user){
							app()->user->setData($user);
						}
						app()->__Whatever__Log->recordUserAction(SystemLog::USER_EDIT, $user->username, $user->id_user);
					}
				}else{
					$errors = $userEditForm->getErrors();
				}
	    		
            	$this->_returnAjax(array(
            		'result' => $ret,
					'detail' => $detail,
					'errors' => $errors
				));
			}
		}else{
			$user->save();	
			$this->render('edit', array(
				'user' => $user,
			)); 
		}
    }
    
    public function actionIndividualOption()
    {
    	if(app()->request->isAjaxRequest){
	        $postData = app()->request->getParam('UserOptionForm', null);
	    	if($postData){
	    		$UserOptionForm = new UserOptionForm();
	    		$UserOptionForm->attributes = $postData;
				$ret = false;
				$detail = $errors = null;
				if($UserOptionForm->validate()){
					$individualConfig = IndividualConfig::model()->findByAttributes(array('id_user' => $postData['id_user']));
					if(empty($individualConfig)){
						$individualConfig = new IndividualConfig();
					}
					$individualConfig->attributes = $postData;
					$ret = $individualConfig->save();
					if($ret){
						app()->__Whatever__Log->recordUserAction(SystemLog::USER_INDIVI_UP, $individualConfig->User->username, $postData['id_user']);
					}
				}else{
					$errors = $UserOptionForm->getErrors();
				}
	    		
            	$this->_returnAjax(array(
            		'result' => $ret,
					'detail' => $detail,
					'errors' => $errors
				));
			}
		}
    }
    
    public function actionIndividual()
    {
    	$user = app()->user->getData();
    	
    	$this->render('individual', array(
    		'users' => array($user),
			'userEditForm' => new UserEditForm(),
    		'userOptionForm' => new UserOptionForm(),
    	));
    }
    
    public function actionGetIndividualInfo()
    {
    	$id_user = app()->request->getParam('id_user', null);
    	if($id_user){
    		if(app()->request->isAjaxRequest){
    			$user = User::model()->findByPk($id_user);
    			
    			$this->_returnAjax(array(
    				'profile' => $user->attributes,
    				'option' => empty($user->IndividualOption)? null : $user->IndividualOption->attributes
    			));
    		}
    	}
    }
	
	public function actionDetail($id_user)
	{
		$id_user = app()->request->getParam('id_user', null);
		if($id_user){
			if(app()->request->isAjaxRequest){
				$user = $this->loadModelByPk($id_user, 'User');
				$this->_returnAjax(
					$user->attributes
				);
			}
		}
	}
	
	public function actionDelete()
	{
		if(app()->request->isAjaxRequest){
			$id_user = app()->request->getPost('id_user', null);
			if($id_user){
				$user = $this->loadModelByPk($id_user, 'User');
				$ret = $user->delete();
				if($ret){
					app()->__Whatever__Log->recordUserAction(SystemLog::USER_DELETE, $user->username, $user->id_user);
				}
				$this->_returnAjax(array(
					'result' => $ret,
					'errors' => $user->getErrors()
				));
			}
		
			$this->_end();
		}
	}
	
	public function actionRole()
	{
		$userRoleAddForm = new UserRoleAddForm();
		$userRole = new UserRole();
		
		$postData = app()->request->getPost('UserRoleAddForm', null);
		if($postData){
			$userRoleAddForm->attributes = $postData;
			$ret = false;
			$detail = $errors = null;
			if($userRoleAddForm->validate()){
				$userRole->attributes = $postData;
				if(!($ret = $userRole->save(true))){
					$errors = $userRole->getErrors();
				}else{
					app()->__Whatever__Log->recordRoleAction(SystemLog::ROLE_ADD, $userRole->name, $userRole->id_user_role);
					
					$detail = $postData;
					$detail['id_user_role'] = $userRole->getPrimaryKey();
				}
			}else{
				$errors = $userRoleAddForm->getErrors();
			}
			
			$this->_returnAjax(
				array(
					'result' => $ret,
					'detail' => $detail,
					'errors' => $errors
				)
			);
		}
		
		$this->render('role', array(
			'userRoleAddForm' => $userRoleAddForm,
			'userRoleEditForm' => new UserRoleEditForm(),
			'userRole' => $userRole
		));
	}
	
	public function actionEditRole()
    {
        $postData = app()->request->getParam('UserRoleEditForm', null);
    	if($postData){
//    		$postData = array_filter($postData);
	        $model = $this->loadModelByPk(empty($postData['id_user_role'])? '' : $postData['id_user_role'], 'UserRole');
	
	        if($model){
	            $model->attributes = $postData;
	            if(app()->request->isAjaxRequest){
	            	$ret = $model->save();
	            	if($ret){
	            		app()->__Whatever__Log->recordRoleAction(SystemLog::ROLE_EDIT, $model->name, $model->id_user_role);
	            	}
	            	
	            	$this->_returnAjax(array(
	            		'result' => $ret,
	            		'detail' => $model->attributes,
	            		'errors' => $model->getErrors()
	            	));
	            }else{
	            	if($model->save()){
	                	$this->redirect(array('view', 'id' => $model->id_user_role));
	            	}
	            }
	        }
	
	        $this->render('edit', array(
	            'model' => $model,
	        ));    		
    	}
    }
    
	public function actionRoleDetail($id_user_role)
	{
		$id_user_role = app()->request->getParam('id_user_role', null);
		if($id_user_role){
			if(app()->request->isAjaxRequest){
				$userRole = $this->loadModelByPk($id_user_role, 'UserRole');
				$this->_returnAjax(
					$userRole->attributes
				);
			}
		}
	}
	
	public function actionDeleteRole()
	{
		if(app()->request->isAjaxRequest){
			$id_user_role = app()->request->getPost('id_user_role', null);
			if($id_user_role){
				$userRole = $this->loadModelByPk($id_user_role, 'UserRole');
				$ret = $userRole->delete();
				if($ret){
					app()->__Whatever__Log->recordRoleAction(SystemLog::ROLE_DELETE, $userRole->name, $userRole->id_user_role);
				}
				
				$this->_returnAjax(array(
					'result' => $ret,
					'errors' => $userRole->getErrors()
				));
			}
		
			$this->_end();
		}
	}
	
	public function actionPermission($selectedRoleId = null, $notification = null)
	{
		$existedRole = CHtml::listData(UserRole::model()->findAll(), 'id_user_role', 'name');
		$existedGroups = CHtml::listData(Group::model()->findAll(), 'id_group', 'name');
		$existedWhmAccounts = CHtml::listData(WhmAccount::model()->findAll(), 'id_account', 'domain');
		
		$this->render('permission', array(
			'existedRole' => $existedRole,
			'selectedRoleId' => $selectedRoleId,
			'notification' => $notification,
		
			'existedGroups' => $existedGroups,
			'existedWhmAccounts' => $existedWhmAccounts
		));
	}
	
	public function actionMidifyPermission()
	{
		$id_user_role = app()->request->getPost('id_user_role', null);
		if($id_user_role){
			$postData = app()->request->getPost('Perm', null);
			if($postData){
				$userRole = $this->loadModelByPk($id_user_role, 'UserRole');
				if($userRole->supreme != 1){
					if($userRole->UserRolePerm){
						// update
						$userRolePerm = $userRole->UserRolePerm;
					}else{
						// add
						$userRolePerm = new UserRolePerm();
					}
					$userRolePerm->attributes = $postData;
					$userRolePerm->save();
					$userRole->updateByPk($id_user_role, array('id_user_role_perm' => $userRolePerm->id_user_role_perm));
					
					app()->__Whatever__Log->recordRoleAction(SystemLog::PER_EDIT, $userRole->name, $userRole->id_user_role);
				}
			}
		}
		
		$this->actionPermission($id_user_role, 'Permission setting sucess');
	}
	
	public function actionModifyAccess()
	{
		$id_user_role = app()->request->getPost('id_user_role', null);
		if($id_user_role){
			$postData = app()->request->getPost('Access', null);
			if($postData){
				$userRole = $this->loadModelByPk($id_user_role, 'UserRole');
				if($userRole->supreme != 1){
					UserRolePermAccount::model()->deleteAllByAttributes(array('id_user_role' => $id_user_role));
					UserRolePermGroup::model()->deleteAllByAttributes(array('id_user_role' => $id_user_role));
					
					$id_group_per = empty($postData['id_group_permitted'])? array() : $postData['id_group_permitted'];
					foreach($id_group_per as $id_group){
						$userRolePermGroup = new UserRolePermGroup();
						$userRolePermGroup->allow_or_deny = 1;
						$userRolePermGroup->id_group = $id_group;
						$userRolePermGroup->id_user_role = $id_user_role;
						$userRolePermGroup->save();
					}
					
					$id_group_deny = empty($postData['id_group_not_permitted'])? array() : $postData['id_group_not_permitted'];
					foreach($id_group_deny as $id_group){
						$userRolePermGroup = new UserRolePermGroup();
						$userRolePermGroup->allow_or_deny = 0;
						$userRolePermGroup->id_group = $id_group;
						$userRolePermGroup->id_user_role = $id_user_role;
						$userRolePermGroup->save();
					}
					
					$id_account_per = empty($postData['id_account_permitted'])? array() : $postData['id_account_permitted'];
					foreach($id_account_per as $id_account){
						$userRolePermAccount = new UserRolePermAccount();
						$userRolePermAccount->allow_or_deny = 1;
						$userRolePermAccount->id_account = $id_account;
						$userRolePermAccount->id_user_role = $id_user_role;
						$userRolePermAccount->save();
					}
				
					$id_account_deny = empty($postData['id_account_not_permitted'])? array() : $postData['id_account_not_permitted'];
					foreach($id_account_deny as $id_account){
						$userRolePermAccount = new UserRolePermAccount();
						$userRolePermAccount->allow_or_deny = 0;
						$userRolePermAccount->id_account = $id_account;
						$userRolePermAccount->id_user_role = $id_user_role;
						$userRolePermAccount->save();
					}
				}
			}
		}

		$this->actionPermission($id_user_role, 'Access setting sucess');
	}
	
	public function actionGetPermissionDetail()
	{
		$id_user_role = app()->request->getParam('id_user_role', null);
		if($id_user_role){
			$userRole = $this->loadModelByPk($id_user_role, 'UserRole');
			if(app()->request->isAjaxRequest){
				$this->_returnAjax(array(
					'role' => $userRole->attributes,
					'perm' => empty($userRole->UserRolePerm)? null : $userRole->UserRolePerm->attributes
				));
			}
		}
	}
	
	public function actionGetAccessDetail()
	{
		$id_user_role = app()->request->getParam('id_user_role', null);
		if($id_user_role){
			$userRole = $this->loadModelByPk($id_user_role, 'UserRole');
			if(app()->request->isAjaxRequest){
				$this->_returnAjax(array(
					'role' => $userRole->attributes,
					'userRolePermAccount' => CHtml::listData(UserRolePermAccount::model()->findAllByAttributes(array('id_user_role' => $id_user_role, 'allow_or_deny' => 1)), 'id_account', 'allow_or_deny'),
					'userRolePermGroup' => CHtml::listData(UserRolePermGroup::model()->findAllByAttributes(array('id_user_role' => $id_user_role, 'allow_or_deny' => 1)), 'id_group', 'allow_or_deny'),
					'userRoleDenyAccount' => CHtml::listData(UserRolePermAccount::model()->findAllByAttributes(array('id_user_role' => $id_user_role, 'allow_or_deny' => 0)), 'id_account', 'allow_or_deny'),
					'userRoleDenyGroup' => CHtml::listData(UserRolePermGroup::model()->findAllByAttributes(array('id_user_role' => $id_user_role, 'allow_or_deny' => 0)), 'id_group', 'allow_or_deny')
				));
			}
		}
	}
	
	public function actionLogout()
	{
		app()->user->logout();
		$this->redirect(array('user/login'));
	}
	
	public function actionLogin()
	{
		$this->layout='//layouts/empty';
		
		$this->render('login', array(
			
		));
	}
	
	public function actionSignup()
	{
		$this->layout='//layouts/empty';
		
		$this->render('signup', array(
			
		));
	}
	
	public function actionCompleteaftersignup()
	{
		$this->layout='//layouts/empty';
		
		$this->render('completeaftersignup', array(
			
		));
	}
	
	public function actionResetRestrictIp()
	{
		$this->layout = 'login';
		
		$token = app()->request->getParam('token', null);
		$token = EmailHelper::decodeToken($token);
		$info = 'Error: Invalid token';
		if(!empty($token['id_user']) && !empty($token['time']) && !empty($token['userIp'])){
			$now = time();
			if($now-$token['time'] <= app()->params['GLOBAL_SETTING']['EMAIL']['RESET_RESTRICT_IP_EXPIRE']){
				$user = User::model()->findByPk($token['id_user']);
				$indivudualConfig = $user->getIndividualConfig();
				
				$restrictIps = $indivudualConfig->getRestrictIp();
				if(!in_array($token['userIp'], $restrictIps)){
					$indivudualConfig->id_user = $token['id_user'];
					$indivudualConfig->restrict_ips = $indivudualConfig->restrict_ips . "\n" . $token['userIp'];
					$indivudualConfig->save();
				}
				$info = "Success: Ip: {$token['userIp']} is allowed now.";
			}else{
				$info = 'Error: Expire request!';
			}
		}

		$this->render('emailcallback', array(
			'info' => $info
		));
	}
	
	public function actionUnsuspendByEmail()
	{
		$this->layout = 'login';
		
		$token = app()->request->getParam('token', null);
		
		$info = 'Error: Invalid token';
		$token = EmailHelper::decodeToken($token);
		if(!empty($token['id_user']) && !empty($token['time'])){
			$now = time();
			if($now-$token['time'] <= app()->params['GLOBAL_SETTING']['EMAIL']['DEFAULT_EMAIL_OPERATION_EXPIRE']){
				$user = User::model()->findByPk($token['id_user']);
				if($user->active()){
					$user->resetLoginattempts();
					$info = "Success: $user->username is actived now.";
				}
			}else{
				$info = 'Error: Expire request!';
			}
		}

		$this->render('emailcallback', array(
			'info' => $info
		));
		
	}
	
	public function actionGetInfo()
	{
		$id_user = app()->request->getParam('id_user', null);
		if($id_user){
			if(app()->request->isAjaxRequest){
				$user = User::model()->findByPk($id_user);
				$this->_returnAjax(
					$user->attributes
				);
			}
		}
	}
	
	public function actionAuthy()
	{
		$now = time();
		if(app()->request->isAjaxRequest){
			$id_user = app()->request->getParam('id_user', null);
			$user = $this->loadModelByPk($id_user, 'User');
			$countryCode = app()->request->getPost('countryCode', null);
			$cellphone = app()->request->getPost('Cellphone', null);
			$ret = false;
			
			if(empty($user->authy_id)){
				$ret = $user->authy($countryCode, $cellphone);
				if($ret){
					app()->__Whatever__Log->recordUserAction(SystemLog::USER_AUTHY_EN, $user->username, $user->id_user);
				}
			}else{
				$user->addError('Authy', 'This user has already been authentic.');
			}

			$this->_returnAjax(array(
				'result' => $ret,
				'errors' => $user->getErrors(),
				'time' => $now
			));
		}
		
		$id_users = app()->request->getParam('id_users', null);
		$renderData = array(
			'id_users' => $id_users,
			'usersDatasource' => array(),
			'countUsers' => 0,
		);
		if($id_users){
			$renderData['usersDatasource'] = CHtml::listData(User::model()->findAllByPk($id_users), 'id_user', 'fullname');
			$renderData['countUsers'] = User::model()->countByAttributes(array('id_user' => $id_users));
		}
		
		$this->render('authy', $renderData);
	}
	
	public function actionDisableAuthy()
	{
		$id_user = app()->request->getParam('id_user', null);
		$user = User::model()->findByPk($id_user);
		
		if(app()->request->isAjaxRequest){
			$ret = $user->disableAuthy();
			if($ret){
				app()->__Whatever__Log->recordUserAction(SystemLog::USER_AUTHY_DIS, $user->username, $user->id_user);
			}
			$this->_returnAjax(array(
				'result' => $ret,
				'errors' => $user->getErrors()
			));
		}
		
	}

	public function actionAuthyLogin()
	{
		$this->layout = 'login';
		$user = clone app()->user->getData();
		
		$postData = app()->request->getPost('authyLoginForm', null);
		if(app()->params['GLOBAL_SETTING']['AUTHY_ENABLED']){
			if($postData){
				if($user->authyVerifyTokens($postData['authy-token'])){
					app()->__Whatever__Log->recordLogin($user->id_user);
					app()->user->setAuthyLogin(true);
					$license = new License();
					$lastLicense = $license->getLast();
					$licensekey = empty($lastLicense->licensekey)? null : $lastLicense->licensekey;
					$localkey = empty($lastLicense->localkey)? null : $lastLicense->localkey;
					$licenseCheckDetails = $license->check_license($licensekey, $localkey);
					if(!empty($licenseCheckDetails['status']) && $licenseCheckDetails['status'] == 'Active'){
						if(!WhmAccount::model()->checkAccountsLimit()){
							app()->user->setAccountLimitExceeded(true);
							$this->redirect(url('default/license', array('licenseError' => 2)));
						}else{
							$this->redirect(array('default/index'));
						}
					}else{
						app()->user->setLicenseAccess(false);
						$this->redirect(url('default/license', array('licenseError' => 1)));
					}
				}
				app()->__Whatever__Log->recordLogin($user->id_user, SystemLog::LOGIN_FALIED, SystemLog::LOGIN_FAILED_REASON_AUTHY);
			}
		}else{
			$user->addError('authyVerifyTokens', t('info', 'Authy Authentication is not enabled for this license'));
		}
		$this->render('authylogin', array(
			'user' => $user
		));
	}
	
	public function actionAuthysms()
	{
		$id_user = app()->request->getParam('id_user', null);
		$user = User::model()->findByPk($id_user);
		
		if(app()->request->isAjaxRequest){
			$this->_returnAjax(array(
				'result' => $user->sendAuthySms(),
				'errors' => $user->getErrors()
			));
		}
	}
	
	public function actions(){
		return array(
			'captcha'=>array(
				'class'=>'CaptchaExtendedAction',
//				'class'=>'CCaptchaAction',
			),
		);
	}
	
	public function accessRules()
	{
		return array(
			array(
				'allow',
				'actions' => array('captcha', 'resetrestrictip', 'unsuspendbyemail'),
				'expression' => 'app()->user->anyone()',
			),
		
			array(
				'allow',
				'actions' => array('login', 'signup', 'completeaftersignup'),
				'expression' => '!app()->user->isLogin()',
				'redirect' => array('default/index')
			),
			
			array(
				'allow',
				'actions' => array('logout'),
				'expression' => 'app()->user->isUser()',
				'redirect' => array('user/login')
			),
			
			array(
				'allow',
				'actions' => array('authylogin', 'authysms'),
				'expression' => '(!app()->user->isAuthyLogin()) && app()->user->isUser()',
				'redirect' => array('user/login')
			),
			
			array(
				'allow',
				'actions' => array('individual', 'getindividualinfo', 'individualoption'),
				'expression' => 'app()->user->isLogin()',
				'redirect' => array('user/login')
			),
			
			array(
				'allow',
				'actions' => array(
					'list', 'edit', 'detail', 'delete', 'authy', 'disableauthy',
					'role', 'editrole', 'roledetail', 'deleterole', 
					'permission', 'midifypermission', 'getpermissiondetail', 'modifyaccess', 'getaccessdetail', 'getinfo'
				),
				'expression' => 'app()->user->isLogin() && app()->user->hasManageUserPerm()',
				'redirect' => array('default/noaccess')
			),

			array(
				'deny',	//should be 'deny', 'allow' is used to give convenient to make test
				'users' => array('*'),
				'redirect' => array('user/login')
			)
		);
	}
	
}